package com.biz.primus.ms.promotion.service.promotion;

import com.biz.primus.base.enums.CommonStatus;
import com.biz.primus.base.exception.utils.AssertUtils;
import com.biz.primus.base.vo.PageVo;
import com.biz.primus.common.vo.SpringPageVO;
import com.biz.primus.model.promotion.exception.PromotionExceptionType;
import com.biz.primus.model.promotion.vo.SpecialOfferProductVo;
import com.biz.primus.model.promotion.vo.SpecialOfferPromotionVo;
import com.biz.primus.ms.base.service.AbstractBaseService;
import com.biz.primus.ms.promotion.dao.po.SpecialOfferPromotion;
import com.biz.primus.ms.promotion.dao.po.SpecialOfferPromotionProduct;
import com.biz.primus.ms.promotion.dao.repository.SpecialOfferPromotionRepository;
import com.biz.primus.ms.promotion.service.feign.ProductFeignService;
import com.biz.primus.ms.promotion.trans.SpecialOfferPromotionPo2VoMapper;
import com.google.common.collect.Lists;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 简单特价后台管理Service
 *
 * @author david-liu
 */
@Service
public class SpecialOfferPromotionManagementServiceImpl extends AbstractBaseService implements SpecialOfferPromotionManagementService {

    @Autowired
    private SpecialOfferPromotionRepository specialOfferPromotionRepository;

    @Autowired
    private ProductFeignService productFeignService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createSpecialOfferPromotion(SpecialOfferPromotionVo vo) {
        AssertUtils.notNull(vo, PromotionExceptionType.ILLEGAL_PARAMETER);
        SpecialOfferPromotion specialOfferPromotion;
        if (Objects.isNull(vo.getId())) {
            specialOfferPromotion = new SpecialOfferPromotion();
            specialOfferPromotion.setId(idService.getNextId());
        } else {
            specialOfferPromotion = specialOfferPromotionRepository.findOne(vo.getId());
        }
        specialOfferPromotion.setName(vo.getName());
        specialOfferPromotion.setDescription(vo.getDescription());
        specialOfferPromotion.setChannels(vo.getChannels());
        if (StringUtils.isNotBlank(vo.getStartTime())) {
            specialOfferPromotion.setStartTime(LocalDateTime.from(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").parse(vo.getStartTime())));
        }
        if (StringUtils.isNotBlank(vo.getEndTime())) {
            specialOfferPromotion.setEndTime(LocalDateTime.from(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").parse(vo.getEndTime())));
        }
        specialOfferPromotion.setEffectMemberLevels((Optional.ofNullable(vo.getEffectMemberLevels()).orElse(Lists.newArrayList()).stream().map(Integer::valueOf).collect(Collectors.toList())));
        specialOfferPromotion.setScope(vo.getScope());
        specialOfferPromotion.setScopeIds(Arrays.stream(StringUtils.split(vo.getScopeIds(), ",")).map(id -> Long.valueOf(StringUtils.trim(id))).collect(Collectors.toList()));
        specialOfferPromotion.setCommonStatus(vo.getCommonStatus());
        List<SpecialOfferPromotionProduct> promotionProducts = specialOfferPromotion.getPromotionProducts();
        if (CollectionUtils.isEmpty(promotionProducts)) {
            promotionProducts = Lists.newArrayList();
            for (SpecialOfferProductVo productVo : vo.getProducts()) {
                SpecialOfferPromotionProduct specialOfferPromotionProduct = new SpecialOfferPromotionProduct();
                specialOfferPromotionProduct.setId(idService.getNextId());
                specialOfferPromotionProduct.setProductId(productVo.getProductId());
                specialOfferPromotionProduct.setPurchaseQuantityLimit(productVo.getPurchaseQuantityLimit());
                specialOfferPromotionProduct.setSpecialOfferPrice(productVo.getSpecialOfferPrice());
                specialOfferPromotionProduct.setSpecialOfferPromotion(specialOfferPromotion);
                promotionProducts.add(specialOfferPromotionProduct);
            }
            specialOfferPromotion.setPromotionProducts(promotionProducts);
        } else {
            Map<Long, SpecialOfferPromotionProduct> promotionProductMap = promotionProducts.stream().collect(Collectors.toMap(SpecialOfferPromotionProduct::getProductId, Function.identity()));
            for (SpecialOfferProductVo productVo : vo.getProducts()) {
                SpecialOfferPromotionProduct specialOfferPromotionProduct = promotionProductMap.get(productVo.getProductId());
                if (Objects.isNull(specialOfferPromotionProduct)) {
                    specialOfferPromotionProduct = new SpecialOfferPromotionProduct();
                    specialOfferPromotionProduct.setId(idService.getNextId());
                    specialOfferPromotionProduct.setProductId(productVo.getProductId());
                    specialOfferPromotionProduct.setPurchaseQuantityLimit(productVo.getPurchaseQuantityLimit());
                    specialOfferPromotionProduct.setSpecialOfferPrice(productVo.getSpecialOfferPrice());
                    specialOfferPromotionProduct.setSpecialOfferPromotion(specialOfferPromotion);
                    promotionProducts.add(specialOfferPromotionProduct);
                } else {
                    specialOfferPromotionProduct.setPurchaseQuantityLimit(productVo.getPurchaseQuantityLimit());
                    specialOfferPromotionProduct.setSpecialOfferPrice(productVo.getSpecialOfferPrice());
                    specialOfferPromotionProduct.setSpecialOfferPromotion(specialOfferPromotion);
                }
            }
        }
        specialOfferPromotionRepository.save(specialOfferPromotion);
        return true;
    }

    @Override
    public SpringPageVO<SpecialOfferPromotionVo> getSpecialOfferPromotions(PageVo pageVo) {
        Page<SpecialOfferPromotion> page = specialOfferPromotionRepository.findAll(pageVo.toPageRequest());
        if (!page.hasContent()) {
            return new SpringPageVO<>();
        } else {
            List<SpecialOfferPromotion> specialOfferPromotions = page.getContent();
            Map<Long, List<SpecialOfferProductVo>> specialOfferProducts = productFeignService.getSpecialOfferProducts(specialOfferPromotions);
            List<SpecialOfferPromotionVo> specialOfferPromotionVos = new SpecialOfferPromotionPo2VoMapper().mapWithList(specialOfferPromotions, specialOfferProducts);
            return new SpringPageVO.Builder<SpecialOfferPromotionVo>().size(page.getSize()).number(page.getNumber()).totalElements(page.getTotalElements()).content(specialOfferPromotionVos).build();
        }
    }

    @Override
    public SpecialOfferPromotionVo getSpecialOfferPromotion(Long promotionId) {
        SpecialOfferPromotion specialOfferPromotion = specialOfferPromotionRepository.findOne(promotionId);
        AssertUtils.notNull(specialOfferPromotion, PromotionExceptionType.ILLEGAL_STATE);
        List<SpecialOfferProductVo> specialOfferProductVos = productFeignService.getSpecialOfferProducts(specialOfferPromotion);
        return new SpecialOfferPromotionPo2VoMapper().map(specialOfferPromotion, specialOfferProductVos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean toggleSpecialOfferPromotionStatus(Long promotionId) {
        SpecialOfferPromotion specialOfferPromotion = specialOfferPromotionRepository.findOne(promotionId);
        AssertUtils.notNull(specialOfferPromotion, PromotionExceptionType.ILLEGAL_STATE);
        specialOfferPromotion.setCommonStatus(CommonStatus.toggle(specialOfferPromotion.getCommonStatus()));
        specialOfferPromotionRepository.save(specialOfferPromotion);
        return true;
    }

}
